package cn.com.coding.config;

import cn.com.coding.framework.security.CaptchaFilter;
import cn.com.coding.framework.security.JwtAccessDeniedHandler;
import cn.com.coding.framework.security.JwtAuthenticationEntryPoint;
import cn.com.coding.framework.security.JwtAuthenticationFilter;
import cn.com.coding.framework.security.JwtLogoutSuccessHandler;
import cn.com.coding.framework.security.LoginFailureHandler;
import cn.com.coding.framework.security.LoginSuccessHandler;
import cn.com.coding.framework.security.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private LoginFailureHandler loginFailureHandler;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private CaptchaFilter captchaFilter;

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Autowired
    UserDetailServiceImpl userDetailService;

    @Autowired
    JwtLogoutSuccessHandler jwtLogoutSuccessHandler;

    // 白名单
    private static final String[] URL_WHITELIST = {"/login", "/logout", "/captcha", "/favicon.ico", "/gd/sysuser/**", "/test/**", "/gd/goodcatelog/**", "/gd/goodinfo/**", "/gd/userinfo/**", "/static/**",
            // swagger
            "/swagger-ui.html/**", "/webjars/**", "/swagger-resources/**", "/v2/**", "/**"
            // swagger end
    };

    @Bean
    JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
        JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
        return jwtAuthenticationFilter;
    }

    /**
     * 告诉 Security 数据库如何加密方式
     *
     * @return
     */
    @Bean
    BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // http.cors().and().csrf().disable() 跨域配置 二
        http.cors().and().csrf().disable()

                // 登录配置
                .formLogin().successHandler(loginSuccessHandler).failureHandler(loginFailureHandler)

                .and().logout().logoutSuccessHandler(jwtLogoutSuccessHandler)

                // 禁用session
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)

                // 配置拦截规则
                .and().authorizeRequests().antMatchers(URL_WHITELIST).permitAll().anyRequest().authenticated()

                // 异常处理器
                .and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).accessDeniedHandler(jwtAccessDeniedHandler)

                // 配置自定义的过滤器
                .and().addFilter(jwtAuthenticationFilter()).addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class);

    }

    /**
     * 配置 UserDetailServiceImpl 委托实现
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailService);
    }
}